xtask\tasks\fmt\house_rules/
cfg_target_arch.rs1use anyhow::anyhow;
5use fs_err::File;
6use std::io::BufRead;
7use std::io::BufReader;
8use std::path::Path;
9
10const SUPPRESS: &str = "xtask-fmt allow-target-arch";
11
12const SUPPRESS_REASON_CPU_INTRINSIC: &str = "cpu-intrinsic";
14const SUPPRESS_REASON_SYS_CRATE: &str = "sys-crate";
17const SUPPRESS_REASON_DEPENDENCY: &str = "dependency";
19const SUPPRESS_REASON_ONEOFF_GUEST_ARCH_IMPL: &str = "oneoff-guest-arch-impl";
22const SUPPRESS_REASON_ONEOFF_FLOWEY: &str = "oneoff-flowey";
24const SUPPRESS_REASON_ONEOFF_PETRI_NATIVE_TEST_DEPS: &str = "oneoff-petri-native-test-deps";
26const SUPPRESS_REASON_ONEOFF_PETRI_HOST_ARCH: &str = "oneoff-petri-host-arch";
28
29fn has_suppress(s: &str) -> bool {
30    let Some((_, after)) = s.split_once(SUPPRESS) else {
31        return false;
32    };
33
34    let after = after.trim();
35    let justification = after.split(' ').next().unwrap();
36
37    let ok = matches!(
38        justification,
39        SUPPRESS_REASON_CPU_INTRINSIC
40            | SUPPRESS_REASON_SYS_CRATE
41            | SUPPRESS_REASON_DEPENDENCY
42            | SUPPRESS_REASON_ONEOFF_GUEST_ARCH_IMPL
43            | SUPPRESS_REASON_ONEOFF_FLOWEY
44            | SUPPRESS_REASON_ONEOFF_PETRI_NATIVE_TEST_DEPS
45            | SUPPRESS_REASON_ONEOFF_PETRI_HOST_ARCH
46    );
47
48    if !ok {
49        log::error!(
50            "invalid justification '{}' (must be one of [sys-crate, cpu-intrinsic]",
51            after.split(' ').next().unwrap()
52        );
53    }
54
55    ok
56}
57
58pub fn check_cfg_target_arch(path: &Path, _fix: bool) -> anyhow::Result<()> {
59    let ext = path
60        .extension()
61        .and_then(|e| e.to_str())
62        .unwrap_or_default();
63
64    if !matches!(ext, "rs") {
65        return Ok(());
66    }
67
68    if path == Path::new(file!()) || path == Path::new(super::PATH_TO_HOUSE_RULES_RS) {
71        return Ok(());
72    }
73
74    if path.starts_with("guest_test_uefi")
90        || path.starts_with("openhcl/openhcl_boot")
91        || path.starts_with("openhcl/minimal_rt")
92        || path.starts_with("openhcl/sidecar")
93        || path.starts_with("support/safe_intrinsics")
94        || path.starts_with("tmk/simple_tmk")
95        || path.starts_with("tmk/tmk_core")
96        || path.starts_with("vm/whp")
97        || path.starts_with("vm/kvm")
98    {
99        return Ok(());
100    }
101
102    let mut error = false;
103
104    let f = BufReader::new(File::open(path)?);
106    let mut prev_line = String::new();
107    for (i, line) in f.lines().enumerate() {
108        let line = line?;
109        if line.contains("target_arch =") || line.contains("CARGO_CFG_TARGET_ARCH") {
110            if !line.trim().starts_with("//") && !has_suppress(&line) && !has_suppress(&prev_line) {
112                error = true;
113                log::error!(
114                    "unjustified `cfg(target_arch = ...)`: {}:{}",
115                    path.display(),
116                    i + 1
117                );
118            }
119        }
120        prev_line = line;
121    }
122
123    if error {
124        Err(anyhow!(
125            "found unjustified uses of `cfg(target_arch = ...)` in {}",
126            path.display()
127        ))
128    } else {
129        Ok(())
130    }
131}